home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Graphics / Ghostscript / source / gxfill.c < prev    next >
C/C++ Source or Header  |  1997-07-02  |  48KB  |  1,508 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gxfill.c */
  20. /* Lower-level path filling procedures */
  21. #include "math_.h"        /* for floor in fixed_mult_quo */
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsstruct.h"
  25. #include "gxfixed.h"
  26. #include "gxdevice.h"
  27. #include "gzpath.h"
  28. #include "gzcpath.h"
  29. #include "gxdcolor.h"
  30. #include "gxhttile.h"
  31. #include "gxistate.h"
  32. #include "gxpaint.h"        /* for prototypes */
  33.  
  34. /* Define which fill algorithm(s) to use. */
  35. #define FILL_SCAN_LINES
  36. #define FILL_CURVES
  37. #define FILL_TRAPEZOIDS
  38.  
  39. /* Define the structure for keeping track of active lines. */
  40. typedef struct active_line_s active_line;
  41. struct active_line_s {
  42.     gs_fixed_point start;        /* x,y where line starts */
  43.     gs_fixed_point end;        /* x,y where line ends */
  44.     gs_fixed_point diff;        /* end - start */
  45. #define al_dx(alp) ((alp)->diff.x)
  46. #define al_dy(alp) ((alp)->diff.y)
  47.     fixed y_fast_max;        /* can do x_at_y in fixed point */
  48.                     /* if y <= y_fast_max */
  49. #define set_al_points(alp, startp, endp)\
  50.   (alp)->diff.x = (endp).x - (startp).x,\
  51.   (alp)->y_fast_max = max_fixed /\
  52.     (((alp)->diff.x >= 0 ? (alp)->diff.x : -(alp)->diff.x) | 1) + (startp).y,\
  53.   (alp)->diff.y = (endp).y - (startp).y,\
  54.   (alp)->start = startp, (alp)->end = endp
  55. #define al_x_at_y(alp, yv)\
  56.   ((yv) == (alp)->end.y ? (alp)->end.x :\
  57.    ((yv) <= (alp)->y_fast_max ?\
  58.     ((yv) - (alp)->start.y) * al_dx(alp) / al_dy(alp) :\
  59.     (n_add1_expr(n_slow_x),\
  60.      fixed_mult_quo(al_dx(alp), (yv) - (alp)->start.y, al_dy(alp)))) +\
  61.    (alp)->start.x)
  62.     fixed x_current;        /* current x position */
  63.     fixed x_next;            /* x position at end of band */
  64.     const segment *pseg;        /* endpoint of this line */
  65.     int direction;            /* direction of line segment */
  66. #define dir_up 1
  67. #define dir_horizontal 0        /* (these are handled specially) */
  68. #define dir_down (-1)
  69.     int curve_k;            /* # of subdivisions for curves, */
  70.                     /* -1 for lines */
  71.     curve_cursor cursor;        /* cursor for curves, */
  72.                     /* unused for lines */
  73. /* "Pending" lines (not reached in the Y ordering yet) use next and prev */
  74. /* to order lines by increasing starting Y.  "Active" lines (being scanned) */
  75. /* use next and prev to order lines by increasing current X, or if the */
  76. /* current Xs are equal, by increasing final X. */
  77.     active_line *prev, *next;
  78. /* Link together active_lines allocated individually */
  79.     active_line *alloc_next;
  80. };
  81. /*
  82.  * The active_line structure isn't really simple, but since its instances
  83.  * only exist temporarily during a fill operation, we don't have to
  84.  * worry about a garbage collection occurring.
  85.  */
  86. gs_private_st_simple(st_active_line, active_line, "active_line");
  87.  
  88. /* Define the ordering criterion for active lines. */
  89. /* The xc argument is a copy of lp2->x_current. */
  90. #define x_precedes(lp1, lp2, xc)\
  91.   (lp1->x_current < xc || (lp1->x_current == xc &&\
  92.    (lp1->start.x > lp2->start.x || lp1->end.x < lp2->end.x)))
  93.  
  94. #ifdef DEBUG
  95. /* Internal procedures for printing and checking active lines. */
  96. private void
  97. print_active_line(const char *label, const active_line *alp)
  98. {    dprintf5("[f]%s 0x%lx(%d): x_current=%f x_next=%f\n",
  99.              label, (ulong)alp, alp->direction,
  100.              fixed2float(alp->x_current), fixed2float(alp->x_next));
  101.     dprintf5("    start=(%f,%f) pt_end=0x%lx(%f,%f)\n",
  102.              fixed2float(alp->start.x), fixed2float(alp->start.y),
  103.              (ulong)alp->pseg,
  104.              fixed2float(alp->end.x), fixed2float(alp->end.y));
  105.     dprintf2("    prev=0x%lx next=0x%lx\n",
  106.          (ulong)alp->prev, (ulong)alp->next);
  107. }
  108. private void
  109. print_line_list(const active_line *flp)
  110. {    const active_line *lp;
  111.     for ( lp = flp; lp != 0; lp = lp->next )
  112.        {    fixed xc = lp->x_current, xn = lp->x_next;
  113.         dprintf3("[f]0x%lx(%d): x_current/next=%g",
  114.                  (ulong)lp, lp->direction,
  115.                  fixed2float(xc));
  116.         if ( xn != xc ) dprintf1("/%g", fixed2float(xn));
  117.         dputc('\n');
  118.        }
  119. }
  120. #define print_al(label,alp)\
  121.   if ( gs_debug_c('F') ) print_active_line(label, alp)
  122. private int
  123. check_line_list(const active_line *flp)
  124. {    const active_line *alp;
  125.  
  126.     if ( flp != 0 )
  127.       for ( alp = flp->prev->next; alp != 0; alp = alp->next )
  128.         if ( alp->next != 0 && alp->next->x_current < alp->x_current )
  129.           {    lprintf("[f]Lines out of order!\n");
  130.         print_active_line("   1:", alp);
  131.         print_active_line("   2:", alp->next);
  132.         return_error(gs_error_Fatal);
  133.           }
  134.     return 0;
  135. }
  136. #else
  137. #define print_al(label,alp) DO_NOTHING
  138. #endif
  139.  
  140. /* Line list structure */
  141. struct line_list_s {
  142.     gs_memory_t *memory;
  143.     active_line *active_area;    /* allocated active_line list */
  144.     active_line *next_active;    /* next allocation slot */
  145.     active_line *limit;        /* limit of local allocation */
  146.     int close_count;        /* # of added closing lines */
  147.     active_line *y_list;        /* Y-sorted list of pending lines */
  148.     active_line *y_line;        /* most recently inserted line */
  149.     active_line x_head;        /* X-sorted list of active lines */
  150. #define x_list x_head.next
  151.         /* Put the arrays last so the scalars will have */
  152.         /* small displacements. */
  153.         /* Allocate a few active_lines locally */
  154.         /* to avoid round trips through the allocator. */
  155. #if arch_small_memory
  156. #  define max_local_active 5        /* don't overburden the stack */
  157. #else
  158. #  define max_local_active 20
  159. #endif
  160.     active_line local_active[max_local_active];
  161. };
  162. typedef struct line_list_s line_list;
  163. typedef line_list _ss *ll_ptr;
  164.  
  165. /* Forward declarations */
  166. private void init_line_list(P2(ll_ptr, gs_memory_t *));
  167. private void unclose_path(P2(gx_path *, int));
  168. private void free_line_list(P1(ll_ptr));
  169. private int add_y_list(P5(gx_path *, ll_ptr, fixed, fixed,
  170.   const gs_fixed_rect *));
  171. private int add_y_line(P4(const segment *, const segment *, int, ll_ptr));
  172. private void near insert_x_new(P2(active_line *, ll_ptr));
  173. private bool near end_x_line(P1(active_line *));
  174. #define fill_loop_proc(proc)\
  175. int proc(P11(ll_ptr, gx_device *,\
  176.   const gx_fill_params *, const gx_device_color *, gs_logical_operation_t,\
  177.   const gs_fixed_rect *, fixed, fixed, fixed, fixed, fixed))
  178. private fill_loop_proc(fill_loop_by_scan_lines);
  179. private fill_loop_proc(fill_loop_by_trapezoids);
  180.  
  181. /* Statistics */
  182. #ifdef DEBUG
  183. #  define n_add1(x) (x++)
  184. #  define n_add1_expr(x) n_add1(x)
  185. #  define n_add(x,n) (x += (n))
  186. private long n_fill;
  187. private long n_fill_alloc;
  188. private long n_y_up;
  189. private long n_y_down;
  190. private long n_horiz;
  191. private long n_x_step;
  192. private long n_slow_x;
  193. private long n_iter;
  194. private long n_find_y;
  195. private long n_band;
  196. private long n_band_step;
  197. private long n_band_fill;
  198. private long n_afill;
  199. private long n_slant;
  200. private long n_slant_shallow;
  201. private long n_sfill;
  202. #else
  203. #  define n_add1(x) DO_NOTHING
  204. #  define n_add1_expr(x) discard(0)
  205. #  define n_add(x,n) DO_NOTHING
  206. #endif
  207.  
  208. /*
  209.  * This is the general path filling algorithm.
  210.  * It uses the center-of-pixel rule for filling.
  211.  * We can implement Microsoft's upper-left-corner-of-pixel rule
  212.  * by subtracting (0.5, 0.5) from all the coordinates in the path.
  213.  *
  214.  * The adjust parameters are a hack for keeping regions
  215.  * from coming out too faint: they specify an amount by which to expand
  216.  * the sides of every filled region.
  217.  * Setting adjust = fixed_half is supposed to produce the effect of Adobe's
  218.  * any-part-of-pixel rule, but it doesn't quite, because of the
  219.  * closed/open interval rule for regions.  We detect this as a special case
  220.  * and do the slightly ugly things necessary to make it work.
  221.  */
  222.  
  223. /*
  224.  * Tweak the fill adjustment if necessary so that (nearly) empty
  225.  * rectangles are guaranteed to produce some output.  This is a hack
  226.  * to work around a bug in the Microsoft Windows PostScript driver,
  227.  * which draws thin lines by filling zero-width rectangles, and in
  228.  * some other drivers that try to fill epsilon-width rectangles.
  229.  */
  230. void
  231. gx_adjust_if_empty(const gs_fixed_rect *pbox, gs_fixed_point *adjust)
  232. {    const fixed
  233.       dx = pbox->q.x - pbox->p.x,
  234.       dy = pbox->q.y - pbox->p.y;
  235.     if ( dx < fixed_half && dy >= int2fixed(2) )
  236.       {    adjust->x = arith_rshift_1(fixed_1 + fixed_epsilon - dx);
  237.         if_debug1('f', "[f]thin adjust_x=%g\n",
  238.               fixed2float(adjust->x));
  239.       }
  240.     else
  241.     if ( dy < fixed_half && dx >= int2fixed(2) )
  242.       {    adjust->y = arith_rshift_1(fixed_1 + fixed_epsilon - dy);
  243.         if_debug1('f', "[f]thin adjust_y=%g\n",
  244.               fixed2float(adjust->y));
  245.       }
  246. }
  247.  
  248. /*
  249.  * Fill a path.  This is the default implementation of the driver
  250.  * fill_path procedure.
  251.  */
  252. int
  253. gx_default_fill_path(gx_device *pdev, const gs_imager_state *pis,
  254.   gx_path *ppath, const gx_fill_params *params,
  255.   const gx_device_color *pdevc, const gx_clip_path *pcpath)
  256. {    gs_fixed_point adjust;
  257. #define adjust_x adjust.x
  258. #define adjust_y adjust.y
  259.     gs_logical_operation_t lop = pis->log_op;
  260.     gs_fixed_rect ibox, bbox;
  261.     gx_device_clip cdev;
  262.     gx_device *dev = pdev;
  263.     gx_device *save_dev = dev;
  264.     gx_path ffpath;
  265.     gx_path *pfpath;
  266.     int code;
  267.     fixed adjust_left, adjust_right, adjust_below, adjust_above;
  268.     int max_fill_band = dev->max_fill_band;
  269. #define no_band_mask ((fixed)(-1) << (sizeof(fixed) * 8 - 1))
  270.     bool fill_by_trapezoids;
  271.     line_list lst;
  272.  
  273.     adjust = params->adjust;
  274.     /*
  275.      * Compute the bounding box before we flatten the path.
  276.      * This can save a lot of time if the path has curves.
  277.      * If the path is neither fully within nor fully outside
  278.      * the quick-check boxes, we could recompute the bounding box
  279.      * and make the checks again after flattening the path,
  280.      * but right now we don't bother.
  281.      */
  282.     gx_path_bbox(ppath, &ibox);
  283.     if ( params->fill_zero_width )
  284.       gx_adjust_if_empty(&ibox, &adjust);
  285.     /* Check the bounding boxes. */
  286.     if_debug6('f', "[f]adjust=%g,%g bbox=(%g,%g),(%g,%g)\n",
  287.           fixed2float(adjust_x), fixed2float(adjust_y),
  288.           fixed2float(ibox.p.x), fixed2float(ibox.p.y),
  289.           fixed2float(ibox.q.x), fixed2float(ibox.q.y));
  290.     if ( pcpath )
  291.       gx_cpath_inner_box(pcpath, &bbox);
  292.     else
  293.       (*dev_proc(dev, get_clipping_box))(dev, &bbox);
  294.     if ( !rect_within(ibox, bbox) )
  295.       {    /*
  296.          * Intersect the path box and the clip bounding box.
  297.          * If the intersection is empty, this fill is a no-op.
  298.          */
  299.         if ( pcpath )
  300.           gx_cpath_outer_box(pcpath, &bbox);
  301.         if_debug4('f', "   outer_box=(%g,%g),(%g,%g)\n",
  302.               fixed2float(bbox.p.x), fixed2float(bbox.p.y),
  303.               fixed2float(bbox.q.x), fixed2float(bbox.q.y));
  304.         rect_intersect(ibox, bbox);
  305.         if ( ibox.p.x - adjust_x >= ibox.q.x + adjust_x ||
  306.              ibox.p.y - adjust_y >= ibox.q.y + adjust_y
  307.            )
  308.         {    /* Intersection of boxes is empty! */
  309.             return 0;
  310.         }
  311. #undef adjust_x
  312. #undef adjust_y
  313.         /*
  314.          * The path is neither entirely inside the inner clip box
  315.          * nor entirely outside the outer clip box.
  316.          * If we had to flatten the path, this is where we would
  317.          * recompute its bbox and make the tests again,
  318.          * but we don't bother right now.
  319.          *
  320.          * If there is a clipping path, set up a clipping device.
  321.          */
  322.         if ( pcpath )
  323.           { dev = (gx_device *)&cdev;
  324.             gx_make_clip_device(&cdev, &cdev, &pcpath->list);
  325.             cdev.target = save_dev;
  326.             cdev.max_fill_band = save_dev->max_fill_band;
  327.             (*dev_proc(dev, open_device))(dev);
  328.           }
  329.       }
  330.     /*
  331.      * Compute the proper adjustment values.
  332.      * To get the effect of the any-part-of-pixel rule,
  333.      * we may have to tweak them slightly.
  334.      * NOTE: We changed the adjust_right/above value from 0.5+epsilon
  335.      * to 0.5 in release 5.01; even though this does the right thing
  336.      * in every case we could imagine, we aren't confident that it's
  337.      * correct.  (The old values were definitely incorrect, since they
  338.      * caused 1-pixel-wide/high objects to color 2 pixels even if
  339.      * they fell exactly on pixel boundaries.)
  340.      */
  341.     if ( adjust.x == fixed_half )
  342.       adjust_left = fixed_half - fixed_epsilon,
  343.       adjust_right = fixed_half /* + fixed_epsilon */;  /* see above */
  344.     else
  345.       adjust_left = adjust_right = adjust.x;
  346.     if ( adjust.y == fixed_half )
  347.       adjust_below = fixed_half - fixed_epsilon,
  348.       adjust_above = fixed_half /* + fixed_epsilon */;  /* see above */
  349.     else
  350.       adjust_below = adjust_above = adjust.y;
  351.     /* Initialize the active line list. */
  352.     init_line_list(&lst, ppath->memory);
  353.     /*
  354.      * We have a choice of two different filling algorithms:
  355.      * scan-line-based and trapezoid-based.  They compare as follows:
  356.      *
  357.      *    Scan    Trap
  358.      *    ----    ----
  359.      *     no    +yes    perfectly accurate Y adjustment
  360.      *     skip    +draw    0-height horizontal lines
  361.      *     slow    +fast    rectangles
  362.      *    +fast     slow    curves
  363.      *    +yes     no    write pixels at most once
  364.      *
  365.      * Normally we use the scan line algorithm for characters, where
  366.      * curve speed is important and no Y adjustment is involved, and for
  367.      * non-idempotent RasterOps, where double pixel writing must be
  368.      * avoided, and the trapezoid algorithm otherwise.
  369.      */
  370. #define double_write_ok lop_is_idempotent(lop)
  371. #ifdef FILL_SCAN_LINES
  372. #  ifdef FILL_TRAPEZOIDS
  373.     fill_by_trapezoids =
  374.       ((adjust_below | adjust_above) != 0 || ppath->curve_count == 0 ||
  375.        params->flatness >= 1.0) && double_write_ok;
  376. #  else
  377.     fill_by_trapezoids = false;
  378. #  endif
  379. #else
  380.     fill_by_trapezoids = double_write_ok;
  381. #endif
  382. #undef double_write_ok
  383.     /*
  384.      * Pre-process curves.  When filling by trapezoids, we need to
  385.      * flatten the path completely; when filling by scan lines, we only
  386.      * need to monotonize it, unless FILL_CURVES is undefined.
  387.      */
  388.     if ( !ppath->curve_count )    /* don't need to flatten */
  389.       pfpath = ppath;
  390.     else
  391. #ifdef FILL_CURVES
  392.     if ( fill_by_trapezoids )
  393.       {    code = gx_path_flatten_accurate(ppath, &ffpath,
  394.                         params->flatness,
  395.                         pis->accurate_curves);
  396.         if ( code < 0 )
  397.           return code;
  398.         pfpath = &ffpath;
  399.       }
  400.     else if ( gx_path_is_monotonic(ppath) )
  401.       pfpath = ppath;
  402.     else
  403.       {    code = gx_path_monotonize(ppath, &ffpath);
  404.         if ( code < 0 )
  405.           return code;
  406.         pfpath = &ffpath;
  407.       }
  408. #else
  409.       {    code = gx_path_flatten_accurate(ppath, &ffpath,
  410.                         params->flatness,
  411.                         pis->accurate_curves);
  412.         if ( code < 0 )
  413.           return code;
  414.         pfpath = &ffpath;
  415.       }
  416. #endif
  417.     if ( (code = add_y_list(pfpath, &lst, adjust_below, adjust_above, &ibox)) < 0 )
  418.       goto nope;
  419.     { fill_loop_proc((*fill_loop));
  420.  
  421.       /* Some short-sighted compilers won't allow a conditional here.... */
  422.       if ( fill_by_trapezoids )
  423.         fill_loop = fill_loop_by_trapezoids;
  424.       else
  425.         fill_loop = fill_loop_by_scan_lines;
  426.       code = (*fill_loop)
  427.         (&lst, dev, params, pdevc, lop, &ibox,
  428.          adjust_left, adjust_right, adjust_below, adjust_above,
  429.          (max_fill_band == 0 ? no_band_mask : int2fixed(-max_fill_band)));
  430.     }
  431. nope:    if ( lst.close_count != 0 )
  432.       unclose_path(pfpath, lst.close_count);
  433.     free_line_list(&lst);
  434.     if ( pfpath != ppath )    /* had to flatten */
  435.       gx_path_release(pfpath);
  436. #ifdef DEBUG
  437.     if ( gs_debug_c('f') )
  438.        {    dputs("[f]  # alloc    up  down  horiz step slowx  iter  find  band bstep bfill\n");
  439.         dprintf5(" %5ld %5ld %5ld %5ld %5ld",
  440.              n_fill, n_fill_alloc, n_y_up, n_y_down, n_horiz);
  441.         dprintf4(" %5ld %5ld %5ld %5ld",
  442.              n_x_step, n_slow_x, n_iter, n_find_y);
  443.         dprintf3(" %5ld %5ld %5ld\n",
  444.              n_band, n_band_step, n_band_fill);
  445.         dputs("[f]    afill slant shall sfill\n");
  446.         dprintf4("       %5ld %5ld %5ld %5ld\n",
  447.              n_afill, n_slant, n_slant_shallow, n_sfill);
  448.        }
  449. #endif
  450.     return code;
  451. }
  452.  
  453. /* Initialize the line list for a path. */
  454. private void
  455. init_line_list(ll_ptr ll, gs_memory_t *mem)
  456. {    ll->memory = mem;
  457.     ll->active_area = 0;
  458.     ll->next_active = ll->local_active;
  459.     ll->limit = ll->next_active + max_local_active;
  460.     ll->close_count = 0;
  461.     ll->y_list = 0;
  462.     ll->y_line = 0;
  463.     n_add1(n_fill);
  464. }
  465.  
  466. /* Unlink any line_close segments added temporarily. */
  467. private void
  468. unclose_path(gx_path *ppath, int count)
  469. {    subpath *psub;
  470.     for ( psub = ppath->first_subpath; count != 0;
  471.           psub = (subpath *)psub->last->next
  472.         )
  473.       if ( psub->last == (segment *)&psub->closer )
  474.       {    segment *prev = psub->closer.prev, *next = psub->closer.next;
  475.         prev->next = next;
  476.         if ( next ) next->prev = prev;
  477.         psub->last = prev;
  478.         count--;
  479.       }
  480. }
  481.  
  482. /* Free the line list. */
  483. private void
  484. free_line_list(ll_ptr ll)
  485. {    gs_memory_t *mem = ll->memory;
  486.     active_line *alp;
  487.  
  488.     /* Free any individually allocated active_lines. */
  489.     while ( (alp = ll->active_area) != 0 )
  490.       {    active_line *next = alp->alloc_next;
  491.         gs_free_object(mem, alp, "active line");
  492.         ll->active_area = next;
  493.       }
  494. }
  495.  
  496. /*
  497.  * Construct a Y-sorted list of segments for rasterizing a path.  We assume
  498.  * the path is non-empty.  Only include non-horizontal lines or (monotonic)
  499.  * curve segments where one endpoint is locally Y-minimal, and horizontal
  500.  * lines that might color some additional pixels.
  501.  */
  502. private int
  503. add_y_list(gx_path *ppath, ll_ptr ll, fixed adjust_below, fixed adjust_above,
  504.   const gs_fixed_rect *pbox)
  505. {    register segment *pseg = (segment *)ppath->first_subpath;
  506.     int close_count = 0;
  507.     /* fixed xmin = pbox->p.x; */    /* not currently used */
  508.     fixed ymin = pbox->p.y;
  509.     /* fixed xmax = pbox->q.x; */    /* not currently used */
  510.     fixed ymax = pbox->q.y;
  511.     int code;
  512.  
  513.     while ( pseg )
  514.        {    /* We know that pseg points to a subpath head (s_start). */
  515.         subpath *psub = (subpath *)pseg;
  516.         segment *plast = psub->last;
  517.         int dir = 2;        /* hack to skip first segment */
  518.         int first_dir, prev_dir;
  519.         segment *prev;
  520.  
  521.         if ( plast->type != s_line_close )
  522.            {    /* Create a fake s_line_close */
  523.             line_close_segment *lp = &psub->closer;
  524.             segment *next = plast->next;
  525.             lp->next = next;
  526.             lp->prev = plast;
  527.             plast->next = (segment *)lp;
  528.             if ( next ) next->prev = (segment *)lp;
  529.             lp->type = s_line_close;
  530.             lp->pt = psub->pt;
  531.             lp->sub = psub;
  532.             psub->last = plast = (segment *)lp;
  533.             ll->close_count++;
  534.            }
  535.         while ( (prev_dir = dir, prev = pseg,
  536.              (pseg = pseg->next) != 0 && pseg->type != s_start)
  537.               )
  538.           {    /*
  539.              * This element is either a line or a monotonic
  540.              * curve segment.
  541.              */
  542.             fixed iy = pseg->pt.y;
  543.             fixed py = prev->pt.y;
  544.             /*
  545.              * Segments falling entirely outside the ibox in Y
  546.              * are treated as though they were horizontal, *
  547.              * i.e., they are never put on the list.
  548.              */
  549. #define compute_dir(xo, xe, yo, ye)\
  550.   (ye > yo ? (ye <= ymin || yo >= ymax ? 0 : dir_up) :\
  551.    ye < yo ? (yo <= ymin || ye >= ymax ? 0 : dir_down) :\
  552.    2)
  553. #define add_dir_lines(prev2, prev, this, pdir, dir)\
  554.   if ( pdir )\
  555.    { if ( (code = add_y_line(prev2, prev, pdir, ll)) < 0 ) return code; }\
  556.   if ( dir )\
  557.    { if ( (code = add_y_line(prev, this, dir, ll)) < 0 ) return code; }
  558.             dir = compute_dir(prev->pt.x, pseg->pt.x, py, iy);
  559.             if ( dir == 2 )
  560.               {    /* Put horizontal lines on the list */
  561.                 /* if they would color any pixels. */
  562.                 if ( fixed2int_pixround(iy - adjust_below) <
  563.                      fixed2int_pixround(iy + adjust_above)
  564.                    )
  565.                   {    n_add1(n_horiz);
  566.                     if ( (code = add_y_line(prev, pseg,
  567.                         dir_horizontal, ll)) < 0
  568.                        )
  569.                       return code;
  570.                   }
  571.                 dir = 0;
  572.               }
  573.             if ( dir > prev_dir )
  574.               { add_dir_lines(prev->prev, prev, pseg, prev_dir, dir);
  575.               }
  576.             else if ( prev_dir == 2 )    /* first segment */
  577.               first_dir = dir;
  578.             if ( pseg == plast )
  579.                {    /*
  580.                  * We skipped the first segment of the
  581.                  * subpath, so the last segment must receive
  582.                  * special consideration.  Note that we have
  583.                  * `closed' all subpaths.
  584.                  */
  585.                 if ( first_dir > dir )
  586.                   { add_dir_lines(prev, pseg, psub->next,
  587.                           dir, first_dir);
  588.                   }
  589.                }
  590.            }
  591. #undef compute_dir
  592. #undef add_dir_lines
  593.        }
  594.     return close_count;
  595. }
  596. /*
  597.  * Internal routine to test a segment and add it to the pending list if
  598.  * appropriate.
  599.  */
  600. private int
  601. add_y_line(const segment *prev_lp, const segment *lp, int dir, ll_ptr ll)
  602. {    gs_fixed_point this, prev;
  603.     register active_line *alp = ll->next_active;
  604.     fixed y_start;
  605.     if ( alp == ll->limit )
  606.        {    /* Allocate separately */
  607.         alp = gs_alloc_struct(ll->memory, active_line,
  608.                       &st_active_line, "active line");
  609.         if ( alp == 0 ) return_error(gs_error_VMerror);
  610.         alp->alloc_next = ll->active_area;
  611.         ll->active_area = alp;
  612.         n_add1(n_fill_alloc);
  613.        }
  614.     else
  615.         ll->next_active++;
  616.     this.x = lp->pt.x;
  617.     this.y = lp->pt.y;
  618.     prev.x = prev_lp->pt.x;
  619.     prev.y = prev_lp->pt.y;
  620.     switch ( (alp->direction = dir) )
  621.       {
  622.       case dir_up:
  623.         y_start = prev.y;
  624.         set_al_points(alp, prev, this);
  625.         alp->pseg = lp;
  626.         break;
  627.       case dir_down:
  628.         y_start = this.y;
  629.         set_al_points(alp, this, prev);
  630.         alp->pseg = prev_lp;
  631.         break;
  632.       case dir_horizontal:
  633.         y_start = this.y;        /* = prev.y */
  634.         alp->start = prev;
  635.         alp->end = this;
  636.         /* Don't need to set dx or y_fast_max */
  637.         alp->pseg = prev_lp;        /* may not need this either */
  638.         break;
  639.        }
  640.     /* Insert the new line in the Y ordering */
  641.        {    register active_line *yp = ll->y_line;
  642.         register active_line *nyp;
  643.         if ( yp == 0 )
  644.            {    alp->next = alp->prev = 0;
  645.             ll->y_list = alp;
  646.            }
  647.         else if ( y_start >= yp->start.y )
  648.            {    /* Insert the new line after y_line */
  649.             while ( n_add1_expr(n_y_up),
  650.                     ((nyp = yp->next) != NULL &&
  651.                  y_start > nyp->start.y)
  652.                   )
  653.               yp = nyp;
  654.             alp->next = nyp;
  655.             alp->prev = yp;
  656.             yp->next = alp;
  657.             if ( nyp ) nyp->prev = alp;
  658.            }
  659.         else
  660.            {    /* Insert the new line before y_line */
  661.             while ( n_add1_expr(n_y_down),
  662.                     ((nyp = yp->prev) != NULL &&
  663.                  y_start < nyp->start.y)
  664.                   )
  665.               yp = nyp;
  666.             alp->prev = nyp;
  667.             alp->next = yp;
  668.             yp->prev = alp;
  669.             if ( nyp ) nyp->next = alp;
  670.             else ll->y_list = alp;
  671.            }
  672.        }
  673.     ll->y_line = alp;
  674.     print_al("add ", alp);
  675.     return 0;
  676. }
  677.  
  678. /* ---------------- Filling loop utilities ---------------- */
  679.  
  680. /* Insert a newly active line in the X ordering. */
  681. private void near
  682. insert_x_new(active_line *alp, ll_ptr ll)
  683. {    register active_line *next;
  684.     register active_line *prev = &ll->x_head;
  685.     register fixed x = alp->start.x;
  686.     alp->x_current = x;
  687.     while ( n_add1_expr(n_x_step),
  688.         (next = prev->next) != 0 && x_precedes(next, alp, x)
  689.            )
  690.         prev = next;
  691.     alp->next = next;
  692.     alp->prev = prev;
  693.     if ( next != 0 )
  694.       next->prev = alp;
  695.     prev->next = alp;
  696. }
  697.  
  698. /* Handle a line segment that just ended.  Return true iff this was */
  699. /* the end of a line sequence. */
  700. private bool near
  701. end_x_line(active_line *alp)
  702. {    const segment *pseg = alp->pseg;
  703.     /*
  704.      * The computation of next relies on the fact that
  705.      * all subpaths have been closed.  When we cycle
  706.      * around to the other end of a subpath, we must be
  707.      * sure not to process the start/end point twice.
  708.      */
  709.     const segment *next =
  710.       (alp->direction == dir_up ?
  711.        (/* Upward line, go forward along path. */
  712.         pseg->type == s_line_close ? /* end of subpath */
  713.          ((const line_close_segment *)pseg)->sub->next :
  714.          pseg->next) :
  715.        (/* Downward line, go backward along path. */
  716.         pseg->type == s_start ? /* start of subpath */
  717.          ((const subpath *)pseg)->last->prev :
  718.          pseg->prev)
  719.       );
  720.     gs_fixed_point npt;
  721.  
  722.     npt.y = next->pt.y;
  723.     if_debug5('F', "[F]ended 0x%lx: pseg=0x%lx y=%f next=0x%lx npt.y=%f\n",
  724.          (ulong)alp, (ulong)pseg, fixed2float(pseg->pt.y),
  725.          (ulong)next, fixed2float(npt.y));
  726.     if ( npt.y <= pseg->pt.y )
  727.        {    /* End of a line sequence */
  728.         active_line *nlp = alp->next;
  729.         alp->prev->next = nlp;
  730.         if ( nlp )
  731.           nlp->prev = alp->prev;
  732.         if_debug1('F', "[F]drop 0x%lx\n", (ulong)alp);
  733.         return true;
  734.        }
  735.     alp->pseg = next;
  736.     npt.x = next->pt.x;
  737.     set_al_points(alp, alp->end, npt);
  738.     print_al("repl", alp);
  739.     return false;
  740. }
  741.  
  742. #define loop_fill_rectangle(x, y, w, h)\
  743.   gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, lop)
  744. #define loop_fill_rectangle_direct(x, y, w, h)\
  745.   (fill_direct ?\
  746.    (*fill_rect)(dev, x, y, w, h, cindex) :\
  747.    gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, lop))
  748.  
  749. /* ---------------- Scan line filling loop ---------------- */
  750.  
  751. /* Forward references */
  752. private void set_scan_line_points(P2(active_line *, fixed));
  753.  
  754. /* Main filling loop. */
  755. private int
  756. fill_loop_by_scan_lines(ll_ptr ll, gx_device *dev,
  757.   const gx_fill_params *params, const gx_device_color *pdevc,
  758.   gs_logical_operation_t lop, const gs_fixed_rect *pbox,
  759.   fixed adjust_left, fixed adjust_right,
  760.   fixed adjust_below, fixed adjust_above, fixed band_mask)
  761. {    int rule = params->rule;
  762.     fixed fixed_flat = float2fixed(params->flatness);
  763.     bool fill_direct = color_writes_pure(pdevc, lop);
  764.     gx_color_index cindex;
  765.     dev_proc_fill_rectangle((*fill_rect));
  766.     active_line *yll = ll->y_list;
  767.     fixed y_limit = pbox->q.y;
  768.     fixed y;
  769.     /*
  770.      * The meaning of adjust_below (B) and adjust_above (A) is that
  771.      * the pixels that would normally be painted at coordinate Y get
  772.      * "smeared" to coordinates Y-B through Y+A-epsilon, inclusive.
  773.      * This is equivalent to saying that the pixels actually painted
  774.      * at coordinate Y are those contributed by scan lines Y-A+epsilon
  775.      * through Y+B, inclusive, or up to Y+B+epsilon, half-open.
  776.      * (A = B = 0 is a special case, equivalent to B = 0, A = epsilon.)
  777.      */
  778.     fixed look_below =
  779.       (adjust_above == fixed_0 ? fixed_0 : adjust_above - fixed_epsilon);
  780.     fixed look_above =
  781.       adjust_below + fixed_epsilon;
  782.     fixed look_height = look_above + look_below;
  783.     bool do_adjust = look_height > fixed_epsilon;
  784.  
  785.     if ( yll == 0 )                /* empty list */
  786.       return 0;
  787.     if ( fill_direct )
  788.       cindex = pdevc->colors.pure,
  789.       fill_rect = dev_proc(dev, fill_rectangle);
  790. #define next_pixel_center(y)\
  791.   (fixed_pixround(y) + fixed_half)
  792.     y = next_pixel_center(yll->start.y) - look_below;    /* first Y sample point */
  793.     ll->x_list = 0;
  794.     ll->x_head.x_current = min_fixed;    /* stop backward scan */
  795.     while ( 1 )
  796.        {    active_line *alp, *nlp;
  797.         fixed x;
  798.         fixed ya = y + look_height;
  799.  
  800.         n_add1(n_iter);
  801.         /* Move newly active lines from y to x list. */
  802.         while ( yll != 0 && yll->start.y < ya )
  803.            {    active_line *ynext = yll->next;    /* insert smashes next/prev links */
  804.             if ( yll->direction == dir_horizontal )
  805.               {    /* Ignore for now. */
  806.               }
  807.             else
  808.               { insert_x_new(yll, ll);
  809.                 set_scan_line_points(yll, fixed_flat);
  810.               }
  811.             yll = ynext;
  812.            }
  813.         /* Check whether we've reached the maximum y. */
  814.         if ( y >= y_limit )
  815.           break;
  816.         if ( ll->x_list == 0 )
  817.            {    /* No active lines, skip to next start */
  818.             if ( yll == 0 ) break;    /* no lines left */
  819.             y = next_pixel_center(yll->start.y) - look_below;
  820.             continue;
  821.            }
  822.  
  823.         /* Update active lines to y. */
  824.         x = min_fixed;
  825.         for ( alp = ll->x_list; alp != 0; alp = nlp )
  826.           {    fixed nx;
  827.  
  828.             nlp = alp->next;
  829. e:            if ( alp->end.y <= y )
  830.               { if ( end_x_line(alp) )
  831.                   continue;
  832.                 set_scan_line_points(alp, fixed_flat);
  833.                 goto e;
  834.               }
  835.             /* Note that if Y adjustment is in effect, */
  836.             /* alp->start.y might be greater than y. */
  837.             nx = alp->x_current =
  838.               (alp->start.y >= y ? alp->start.x :
  839.                alp->curve_k < 0 ?
  840.                al_x_at_y(alp, y) :
  841.                gx_curve_x_at_y(&alp->cursor, y));
  842.             if ( nx < x )
  843.               { /* Move this line backward in the list. */
  844.                 active_line *ilp = alp;
  845.                 while ( nx < (ilp = ilp->prev)->x_current )
  846.                   ;
  847.                 /* Now ilp->x_current <= nx < ilp->next->x_cur. */
  848.                 alp->prev->next = alp->next;
  849.                 if ( alp->next )
  850.                   alp->next->prev = alp->prev;
  851.                 if ( ilp->next )
  852.                   ilp->next->prev = alp;
  853.                 alp->next = ilp->next;
  854.                 ilp->next = alp;
  855.                 alp->prev = ilp;
  856.                 continue;
  857.               }
  858.             x = nx;
  859.           }
  860.  
  861.         /* Fill inside regions at y. */
  862.         {    int inside = 0;
  863.             int x1_prev = min_int;
  864.  
  865.             /* rule = -1 for winding number rule, i.e. */
  866.             /* we are inside if the winding number is non-zero; */
  867.             /* rule = 1 for even-odd rule, i.e. */
  868.             /* we are inside if the winding number is odd. */
  869. #define inside_path_p() ((inside & rule) != 0)
  870.             n_add1(n_band);
  871.             for ( alp = ll->x_list; alp != 0; alp = alp->next )
  872.               {    /* We're outside a filled region. */
  873.                 int x0 = fixed2int_pixround(alp->x_current -
  874.                                 adjust_left);
  875.  
  876.                 /*
  877.                  * This doesn't handle lines that cross
  878.                  * within the adjustment region, but it's a
  879.                  * good start.
  880.                   */
  881.                 if ( do_adjust && alp->end.x < alp->start.x )
  882.                   { fixed xa = (alp->end.y < ya ? alp->end.x :
  883.                         alp->curve_k < 0 ?
  884.                         al_x_at_y(alp, ya) :
  885.                         gx_curve_x_at_y(&alp->cursor,
  886.                                 ya));
  887.                     int x0a = fixed2int_pixround(xa -
  888.                                  adjust_left);
  889.  
  890.                     if ( x0a < x0 )
  891.                       x0 = x0a;
  892.                   }
  893.                 for ( ; ; )
  894.                   { /* We're inside a filled region. */
  895.                     print_al("step", alp);
  896.                     n_add1(n_band_step);
  897.                     inside += alp->direction;
  898.                     if ( !inside_path_p() )
  899.                       break;
  900.                     /*
  901.                      * Since we're dealing with closed
  902.                      * paths, the test for alp == 0
  903.                      * shouldn't be needed, but we may have
  904.                      * omitted lines that are to the right
  905.                      * of the clipping region.  */
  906.                     if ( (alp = alp->next) == 0 )
  907.                       goto out;
  908.                   }
  909. #undef inside_path_p
  910.                 /*
  911.                  * We just went from inside to outside, so
  912.                  * fill the region.  Avoid writing pixels
  913.                  * twice.
  914.                  */
  915.  
  916.                 if ( x0 < x1_prev )
  917.                   x0 = x1_prev;
  918.                 { int x1 = fixed2int_rounded(alp->x_current +
  919.                                  adjust_right);
  920.  
  921.                   if ( do_adjust && alp->end.x > alp->start.x )
  922.                     { fixed xa = (alp->end.y < ya ?
  923.                           alp->end.x :
  924.                           alp->curve_k < 0 ?
  925.                           al_x_at_y(alp, ya) :
  926.                           gx_curve_x_at_y(&alp->cursor,
  927.                                   ya));
  928.                       int x1a = fixed2int_rounded(xa +
  929.                                 adjust_right);
  930.                       if ( x1a > x1 )
  931.                     x1 = x1a;
  932.                     }
  933.                   if ( x1 > x0 )
  934.                     { int code =
  935.                     loop_fill_rectangle_direct(x0,
  936.                             fixed2int_var(y),
  937.                             x1 - x0, 1);
  938.                       if_debug3('F', "[F]drawing [%d:%d),%d\n",
  939.                         x0, x1, fixed2int_var(y));
  940.                       if ( code < 0 )
  941.                     return code;
  942.                       x1_prev = x1;
  943.                     }
  944.                 }
  945.               }
  946. out:            ;
  947.           }
  948.         y += fixed_1;
  949.        }
  950.     return 0;
  951. }
  952.  
  953. private void
  954. set_scan_line_points(active_line *alp, fixed fixed_flat)
  955. {    const segment *pseg = alp->pseg;
  956.     const gs_fixed_point *pp0;
  957.  
  958.     if ( alp->direction < 0 )
  959.       { pseg =
  960.           (pseg->type == s_line_close ?
  961.            ((const line_close_segment *)pseg)->sub->next :
  962.            pseg->next);
  963.         if ( pseg->type != s_curve )
  964.           { alp->curve_k = -1;
  965.         return;
  966.           }
  967.         pp0 = &alp->end;
  968.       }
  969.     else
  970.       { if ( pseg->type != s_curve )
  971.           { alp->curve_k = -1;
  972.         return;
  973.           }
  974.         pp0 = &alp->start;
  975.       }
  976. #define pcseg ((const curve_segment *)pseg)
  977.     alp->curve_k =
  978.       gx_curve_log2_samples(pp0->x, pp0->y, pcseg, fixed_flat);
  979.     gx_curve_cursor_init(&alp->cursor, pp0->x, pp0->y, pcseg,
  980.                  alp->curve_k);
  981. #undef pcseg
  982. }
  983.  
  984. /* ---------------- Trapezoid filling loop ---------------- */
  985.  
  986. /* Forward references */
  987. private int near fill_slant_adjust(P12(fixed, fixed, fixed, fixed, fixed,
  988.   fixed, fixed, fixed, const gs_fixed_rect *,
  989.   const gx_device_color *, gx_device *, gs_logical_operation_t));
  990. private void near resort_x_line(P1(active_line *));
  991.  
  992. /****** PATCH ******/
  993. #define loop_fill_trapezoid_fixed(fx0, fw0, fy0, fx1, fw1, fh)\
  994.   loop_fill_trap(dev, fx0, fw0, fy0, fx1, fw1, fh, pbox, pdevc, lop)
  995. private int
  996. loop_fill_trap(gx_device *dev, fixed fx0, fixed fw0, fixed fy0,
  997.   fixed fx1, fixed fw1, fixed fh, const gs_fixed_rect *pbox,
  998.   const gx_device_color *pdevc, gs_logical_operation_t lop)
  999. {    fixed fy1 = fy0 + fh;
  1000.     fixed ybot = max(fy0, pbox->p.y);
  1001.     fixed ytop = min(fy1, pbox->q.y);
  1002.     gs_fixed_edge left, right;
  1003.  
  1004.     if ( ybot >= ytop )
  1005.       return 0;
  1006.     left.start.y = right.start.y = fy0;
  1007.     left.end.y = right.end.y = fy1;
  1008.     right.start.x = (left.start.x = fx0) + fw0;
  1009.     right.end.x = (left.end.x = fx1) + fw1;
  1010.     return (*dev_proc(dev, fill_trapezoid))
  1011.       (dev, &left, &right, ybot, ytop, false, pdevc, lop);
  1012. }
  1013. /****** END PATCH ******/
  1014.  
  1015. /* Main filling loop.  Takes lines off of y_list and adds them to */
  1016. /* x_list as needed.  band_mask limits the size of each band, */
  1017. /* by requiring that ((y1 - 1) & band_mask) == (y0 & band_mask). */
  1018. private int
  1019. fill_loop_by_trapezoids(ll_ptr ll, gx_device *dev,
  1020.   const gx_fill_params *params, const gx_device_color *pdevc,
  1021.   gs_logical_operation_t lop, const gs_fixed_rect *pbox,
  1022.   fixed adjust_left, fixed adjust_right,
  1023.   fixed adjust_below, fixed adjust_above, fixed band_mask)
  1024. {    int rule = params->rule;
  1025.     const fixed y_limit = pbox->q.y;
  1026.     active_line *yll = ll->y_list;
  1027.     fixed y;
  1028.     int code;
  1029.     bool fill_direct = color_writes_pure(pdevc, lop);
  1030.     gx_color_index cindex;
  1031.     dev_proc_fill_rectangle((*fill_rect));
  1032. /*
  1033.  * Define a faster test for
  1034.  *    fixed2int_pixround(y - below) != fixed2int_pixround(y + above)
  1035.  * where we know
  1036.  *    0 <= below <= _fixed_pixround_v,
  1037.  *    0 <= above <= min(fixed_half, fixed_1 - below).
  1038.  * Subtracting out the integer parts, this is equivalent to
  1039.  *    fixed2int_pixround(fixed_fraction(y) - below) !=
  1040.  *      fixed2int_pixround(fixed_fraction(y) + above)
  1041.  * or to
  1042.  *    fixed2int(fixed_fraction(y) + _fixed_pixround_v - below) !=
  1043.  *      fixed2int(fixed_fraction(y) + _fixed_pixround_v + above)
  1044.  * Letting A = _fixed_pixround_v - below and B = _fixed_pixround_v + above,
  1045.  * we can rewrite this as
  1046.  *    fixed2int(fixed_fraction(y) + A) != fixed2int(fixed_fraction(y) + B)
  1047.  * Because of the range constraints given above, this is true precisely when
  1048.  *    fixed_fraction(y) + A < fixed_1 && fixed_fraction(y) + B >= fixed_1
  1049.  * or equivalently
  1050.  *    fixed_fraction(y + B) < B - A.
  1051.  * i.e.
  1052.  *    fixed_fraction(y + _fixed_pixround_v + above) < below + above
  1053.  */
  1054.     fixed y_span_delta = _fixed_pixround_v + adjust_above;
  1055.     fixed y_span_limit = adjust_below + adjust_above;
  1056. #define adjusted_y_spans_pixel(y)\
  1057.   fixed_fraction((y) + y_span_delta) < y_span_limit
  1058.  
  1059.     if ( yll == 0 ) return 0;        /* empty list */
  1060.     if ( fill_direct )
  1061.       cindex = pdevc->colors.pure,
  1062.       fill_rect = dev_proc(dev, fill_rectangle);
  1063.     y = yll->start.y;            /* first Y value */
  1064.     ll->x_list = 0;
  1065.     ll->x_head.x_current = min_fixed;    /* stop backward scan */
  1066.     while ( 1 )
  1067.        {    fixed y1;
  1068.         active_line *endp, *alp, *stopx;
  1069.         fixed x;
  1070.         int draw;
  1071.  
  1072.         n_add1(n_iter);
  1073.         /* Move newly active lines from y to x list. */
  1074.         while ( yll != 0 && yll->start.y == y )
  1075.            {    active_line *ynext = yll->next;    /* insert smashes next/prev links */
  1076.             if ( yll->direction == dir_horizontal )
  1077.               {    /* This is a hack to make sure that */
  1078.                 /* isolated horizontal lines get stroked. */
  1079.                 int yi = fixed2int_pixround(y - adjust_below);
  1080.                 int xi, wi;
  1081.                 if ( yll->start.x <= yll->end.x )
  1082.                   xi = fixed2int_pixround(yll->start.x -
  1083.                               adjust_left),
  1084.                   wi = fixed2int_pixround(yll->end.x +
  1085.                               adjust_right) - xi;
  1086.                 else
  1087.                   xi = fixed2int_pixround(yll->end.x -
  1088.                               adjust_left),
  1089.                   wi = fixed2int_pixround(yll->start.x +
  1090.                               adjust_right) - xi;
  1091.                 code = loop_fill_rectangle_direct(xi, yi, wi, 1);
  1092.                 if ( code < 0 )
  1093.                   return code;
  1094.               }
  1095.             else
  1096.               insert_x_new(yll, ll);
  1097.             yll = ynext;
  1098.            }
  1099.         /* Check whether we've reached the maximum y. */
  1100.         if ( y >= y_limit ) break;
  1101.         if ( ll->x_list == 0 )
  1102.            {    /* No active lines, skip to next start */
  1103.             if ( yll == 0 ) break;    /* no lines left */
  1104.             y = yll->start.y;
  1105.             continue;
  1106.            }
  1107.  
  1108.         /* Find the next evaluation point. */
  1109.         /* Start by finding the smallest y value */
  1110.         /* at which any currently active line ends */
  1111.         /* (or the next to-be-active line begins). */
  1112.         y1 = (yll != 0 ? yll->start.y : y_limit);
  1113.         /* Make sure we don't exceed the maximum band height. */
  1114.         { fixed y_band = y | ~band_mask;
  1115.           if ( y1 > y_band ) y1 = y_band + 1;
  1116.         }
  1117.         for ( alp = ll->x_list; alp != 0; alp = alp->next )
  1118.           if ( alp->end.y < y1 ) y1 = alp->end.y;
  1119. #ifdef DEBUG
  1120.         if ( gs_debug_c('F') )
  1121.           {    dprintf2("[F]before loop: y=%f y1=%f:\n",
  1122.                  fixed2float(y), fixed2float(y1));
  1123.             print_line_list(ll->x_list);
  1124.           }
  1125. #endif
  1126.         /* Now look for line intersections before y1. */
  1127.         x = min_fixed;
  1128. #define have_pixels()\
  1129.   (fixed_pixround(y - adjust_below) < fixed_pixround(y1 + adjust_above))
  1130.         draw = (have_pixels() ? 1 : -1);
  1131.         /*
  1132.          * Loop invariants:
  1133.          *    alp = endp->next;
  1134.          *    for all lines lp from stopx up to alp,
  1135.          *      lp->x_next = al_x_at_y(lp, y1).
  1136.          */
  1137.         for ( alp = stopx = ll->x_list;
  1138.               n_add1_expr(n_find_y), alp != 0;
  1139.              endp = alp, alp = alp->next
  1140.             )
  1141.            {    fixed nx = al_x_at_y(alp, y1);
  1142.             fixed dx_old, dx_den;
  1143.             /* Check for intersecting lines. */
  1144.             if ( nx >= x )
  1145.                 x = nx;
  1146.             else if
  1147.                ( draw >= 0 && /* don't bother if no pixels */
  1148.                  (dx_old = alp->x_current - endp->x_current) >= 0 &&
  1149.                  (dx_den = dx_old + endp->x_next - nx) > dx_old
  1150.                )
  1151.                {    /* Make a good guess at the intersection */
  1152.                 /* Y value using only local information. */
  1153.                 fixed dy = y1 - y, y_new;
  1154.                 if_debug3('f', "[f]cross: dy=%g, dx_old=%g, dx_new=%g\n",
  1155.                   fixed2float(dy), fixed2float(dx_old),
  1156.                   fixed2float(dx_den - dx_old));
  1157.                 /* Do the computation in single precision */
  1158.                 /* if the values are small enough. */
  1159.                 y_new =
  1160.                   ((dy | dx_old) < 1L << (size_of(fixed)*4-1) ?
  1161.                    dy * dx_old / dx_den :
  1162.                    fixed_mult_quo(dy, dx_old, dx_den))
  1163.                   + y;
  1164.                 /* The crossing value doesn't have to be */
  1165.                 /* very accurate, but it does have to be */
  1166.                 /* greater than y and less than y1. */
  1167.                 if_debug3('f', "[f]cross y=%g, y_new=%g, y1=%g\n",
  1168.                   fixed2float(y), fixed2float(y_new),
  1169.                   fixed2float(y1));
  1170.                 stopx = alp;
  1171.                 if ( y_new <= y ) y_new = y + 1;
  1172.                 if ( y_new < y1 )
  1173.                    {    y1 = y_new;
  1174.                     nx = al_x_at_y(alp, y1);
  1175.                     draw = 0;
  1176.                    }
  1177.                 if ( nx > x ) x = nx;
  1178.                }
  1179.             alp->x_next = nx;
  1180.            }
  1181.         /* Recompute next_x for lines before the intersection. */
  1182.         for ( alp = ll->x_list; alp != stopx; alp = alp->next )
  1183.           alp->x_next = al_x_at_y(alp, y1);
  1184. #ifdef DEBUG
  1185.         if ( gs_debug_c('F') )
  1186.           {    dprintf1("[F]after loop: y1=%f\n", fixed2float(y1));
  1187.             print_line_list(ll->x_list);
  1188.           }
  1189. #endif
  1190.         /* Fill a multi-trapezoid band for the active lines. */
  1191.         /* Don't bother if no pixel centers lie within the band. */
  1192.         if ( draw > 0 || (draw == 0 && have_pixels()) )
  1193.         {
  1194.  
  1195. /*******************************************************************/
  1196. /* For readability, we start indenting from the left margin again. */
  1197. /*******************************************************************/
  1198.  
  1199.     fixed height = y1 - y;
  1200.     fixed xlbot, xltop;  /* as of last "outside" line */
  1201.     int inside = 0;
  1202.     active_line *nlp;
  1203.  
  1204.     n_add1(n_band);
  1205.     for ( x = min_fixed, alp = ll->x_list; alp != 0; alp = nlp )
  1206.        {    fixed xbot = alp->x_current;
  1207.         fixed xtop = alp->x_current = alp->x_next;
  1208. #define nx xtop
  1209.         fixed wtop;
  1210.         int xi, xli;
  1211.         int code;
  1212.  
  1213.         print_al("step", alp);
  1214.         n_add1(n_band_step);
  1215.         nlp = alp->next;
  1216.         /* Handle ended or out-of-order lines.  After this, */
  1217.         /* the only member of alp we use is alp->direction. */
  1218.         if ( alp->end.y != y1 || !end_x_line(alp) )
  1219.           { if ( nx <= x )
  1220.               resort_x_line(alp);
  1221.             else
  1222.               x = nx;
  1223.           }
  1224. #undef nx
  1225.     /* rule = -1 for winding number rule, i.e. */
  1226.     /* we are inside if the winding number is non-zero; */
  1227.     /* rule = 1 for even-odd rule, i.e. */
  1228.     /* we are inside if the winding number is odd. */
  1229. #define inside_path_p() ((inside & rule) != 0)
  1230.         if ( !inside_path_p() )        /* i.e., outside */
  1231.            {    inside += alp->direction;
  1232.             if ( inside_path_p() )    /* about to go in */
  1233.               xlbot = xbot, xltop = xtop;
  1234.             continue;
  1235.            }
  1236.         /* We're inside a region being filled. */
  1237.         inside += alp->direction;
  1238.         if ( inside_path_p() )        /* not about to go out */
  1239.           continue;
  1240. #undef inside_path_p
  1241.         /* We just went from inside to outside, so fill the region. */
  1242.         wtop = xtop - xltop;
  1243.         n_add1(n_band_fill);
  1244.         /* If lines are temporarily out of */
  1245.         /* order, wtop might be negative. */
  1246.         /* Patch this up now. */
  1247.         if ( wtop < 0 )
  1248.           {    if_debug2('f', "[f]patch %g,%g\n",
  1249.                   fixed2float(xltop), fixed2float(xtop));
  1250.             xtop = xltop += arith_rshift(wtop, 1);
  1251.             wtop = 0;
  1252.           }
  1253.         if ( (adjust_left | adjust_right) != 0 )
  1254.         {    xlbot -= adjust_left;  xbot += adjust_right;
  1255.             xltop -= adjust_left;  xtop += adjust_right;
  1256.             wtop = xtop - xltop;
  1257.         }
  1258.         if ( (xli = fixed2int_var_pixround(xltop)) ==
  1259.               fixed2int_var_pixround(xlbot) &&
  1260.              (xi = fixed2int_var_pixround(xtop)) ==
  1261.               fixed2int_var_pixround(xbot)
  1262.            )
  1263.           {    /* Rectangle. */
  1264.             int yi = fixed2int_pixround(y - adjust_below);
  1265.             int wi = fixed2int_pixround(y1 + adjust_above) - yi;
  1266.             code = loop_fill_rectangle_direct(xli, yi,
  1267.                               xi - xli, wi);
  1268.           }
  1269.         else if ( (adjust_below | adjust_above) != 0 )
  1270.         {    /*
  1271.              * We want to get the effect of filling an area whose
  1272.              * outline is formed by dragging a square of side adj2
  1273.              * along the border of the trapezoid.  This is *not*
  1274.              * equivalent to simply expanding the corners by
  1275.              * adjust: There are 3 cases needing different
  1276.              * algorithms, plus rectangles as a fast special case.
  1277.              */
  1278.             fixed wbot = xbot - xlbot;
  1279.             if ( xltop <= xlbot )
  1280.              { if ( xtop >= xbot )
  1281.                  {    /* Top wider than bottom. */
  1282.                 code = loop_fill_trapezoid_fixed(
  1283.                     xlbot, wbot, y - adjust_below,
  1284.                     xltop, wtop, height);
  1285.                 if ( adjusted_y_spans_pixel(y1) )
  1286.                    {    if ( code < 0 ) return code;
  1287.                     n_add1(n_afill);
  1288.                     code = loop_fill_rectangle_direct(
  1289.                         xli, fixed2int_pixround(y1 - adjust_below),
  1290.                         fixed2int_var_pixround(xtop) - xli, 1);
  1291.                    }
  1292.                  }
  1293.                else
  1294.                 {    /* Slanted trapezoid. */
  1295.                 code = fill_slant_adjust(xlbot, xbot, y,
  1296.                     xltop, xtop, height, adjust_below,
  1297.                     adjust_above, pbox,
  1298.                     pdevc, dev, lop);
  1299.                 }
  1300.              }
  1301.             else
  1302.              { if ( xtop <= xbot )
  1303.                 {    /* Bottom wider than top. */
  1304.                 if ( adjusted_y_spans_pixel(y) )
  1305.                    {    n_add1(n_afill);
  1306.                     xli = fixed2int_var_pixround(xlbot);
  1307.                     code = loop_fill_rectangle_direct(
  1308.                         xli, fixed2int_pixround(y - adjust_below),
  1309.                         fixed2int_var_pixround(xbot) - xli, 1);
  1310.                     if ( code < 0 ) return code;
  1311.                    }
  1312.                 code = loop_fill_trapezoid_fixed(
  1313.                     xlbot, wbot, y + adjust_above,
  1314.                     xltop, wtop, height);
  1315.                 }
  1316.                else
  1317.                 {    /* Slanted trapezoid. */
  1318.                 code = fill_slant_adjust(xlbot, xbot, y,
  1319.                     xltop, xtop, height, adjust_below,
  1320.                     adjust_above, pbox,
  1321.                     pdevc, dev, lop);
  1322.                 }
  1323.              }
  1324.         }
  1325.         else        /* No Y adjustment. */
  1326.           code = loop_fill_trapezoid_fixed(xlbot, xbot - xlbot,
  1327.                            y, xltop, wtop, height);
  1328.         if ( code < 0 ) return code;
  1329.        }
  1330.  
  1331. /**************************************************************/
  1332. /* End of section requiring less indentation for readability. */
  1333. /**************************************************************/
  1334.  
  1335.         }
  1336.         else
  1337.           {    /* Just scan for ended or out-of-order lines. */
  1338.             active_line *nlp;
  1339.             for ( x = min_fixed, alp = ll->x_list; alp != 0;
  1340.                   alp = nlp
  1341.                 )
  1342.               {    fixed nx = alp->x_current = alp->x_next;
  1343.                 nlp = alp->next;
  1344.                 if_debug4('F',
  1345.                       "[F]check 0x%lx,x=%g 0x%lx,x=%g\n",
  1346.                       (ulong)alp->prev, fixed2float(x),
  1347.                       (ulong)alp, fixed2float(nx));
  1348.                 if ( alp->end.y == y1 )
  1349.                   {    if ( end_x_line(alp) )
  1350.                       continue;
  1351.                   }
  1352.                 if ( nx <= x )
  1353.                   resort_x_line(alp);
  1354.                 else
  1355.                   x = nx;
  1356.               }
  1357.           }
  1358. #ifdef DEBUG
  1359.         if ( gs_debug_c('f') )
  1360.           { int code = check_line_list(ll->x_list);
  1361.             if ( code < 0 )
  1362.               return code;
  1363.           }
  1364. #endif
  1365.         y = y1;
  1366.        }
  1367.     return 0;
  1368. }
  1369.  
  1370. /*
  1371.  * Handle the case of a slanted trapezoid with adjustment.
  1372.  * To do this exactly right requires filling a central trapezoid
  1373.  * (or rectangle) plus two horizontal almost-rectangles.
  1374.  */
  1375. private int near
  1376. fill_slant_adjust(fixed xlbot, fixed xbot, fixed y,
  1377.   fixed xltop, fixed xtop, fixed height, fixed adjust_below,
  1378.   fixed adjust_above, const gs_fixed_rect *pbox,
  1379.   const gx_device_color *pdevc, gx_device *dev,
  1380.   gs_logical_operation_t lop)
  1381. {    fixed y1 = y + height;
  1382.     dev_proc_fill_trapezoid((*fill_trap)) =
  1383.       dev_proc(dev, fill_trapezoid);
  1384.     const fixed yb = y - adjust_below;
  1385.     const fixed ya = y + adjust_above;
  1386.     const fixed y1b = y1 - adjust_below;
  1387.     const fixed y1a = y1 + adjust_above;
  1388.     const gs_fixed_edge *plbot;
  1389.     const gs_fixed_edge *prbot;
  1390.     const gs_fixed_edge *pltop;
  1391.     const gs_fixed_edge *prtop;
  1392.     gs_fixed_edge vert_left, slant_left, vert_right, slant_right;
  1393.     int code;
  1394.  
  1395.     n_add1(n_slant);
  1396.  
  1397.     /* Set up all the edges, even though we may not need them all. */
  1398.  
  1399.     if ( xlbot < xltop )    /* && xbot < xtop */
  1400.       { vert_left.start.x = vert_left.end.x = xlbot;
  1401.         vert_left.start.y = yb, vert_left.end.y = ya;
  1402.         vert_right.start.x = vert_right.end.x = xtop;
  1403.         vert_right.start.y = y1b, vert_right.end.y = y1a;
  1404.         slant_left.start.y = ya, slant_left.end.y = y1a;
  1405.         slant_right.start.y = yb, slant_right.end.y = y1b;
  1406.         plbot = &vert_left, prbot = &slant_right,
  1407.           pltop = &slant_left, prtop = &vert_right;
  1408.       }
  1409.     else
  1410.       { vert_left.start.x = vert_left.end.x = xltop;
  1411.         vert_left.start.y = y1b, vert_left.end.y = y1a;
  1412.         vert_right.start.x = vert_right.end.x = xbot;
  1413.         vert_right.start.y = yb, vert_right.end.y = ya;
  1414.         slant_left.start.y = yb, slant_left.end.y = y1b;
  1415.         slant_right.start.y = ya, slant_right.end.y = y1a;
  1416.         plbot = &slant_left, prbot = &vert_right,
  1417.           pltop = &vert_left, prtop = &slant_right;
  1418.       }
  1419.     slant_left.start.x = xlbot, slant_left.end.x = xltop;
  1420.     slant_right.start.x = xbot, slant_right.end.x = xtop;
  1421.  
  1422.     if ( ya >= y1b )
  1423.       {    /*
  1424.          * The upper and lower adjustment bands overlap.
  1425.          * Since the entire entity is less than 2 pixels high
  1426.          * in this case, we could handle it very efficiently
  1427.          * with no more than 2 rectangle fills, but for right now
  1428.          * we don't attempt to do this.
  1429.          */
  1430.         int iyb = fixed2int_var_pixround(yb);
  1431.         int iya = fixed2int_var_pixround(ya);
  1432.         int iy1b = fixed2int_var_pixround(y1b);
  1433.         int iy1a = fixed2int_var_pixround(y1a);
  1434.  
  1435.         n_add1(n_slant_shallow);
  1436.         if ( iy1b > iyb )
  1437.           { code = (*fill_trap)(dev, plbot, prbot,
  1438.                     yb, y1b, false, pdevc, lop);
  1439.             if ( code < 0 )
  1440.               return code;
  1441.           }
  1442.         if ( iya > iy1b )
  1443.           { int ix = fixed2int_var_pixround(vert_left.start.x);
  1444.             int iw = fixed2int_var_pixround(vert_right.start.x) - ix;
  1445.             code = loop_fill_rectangle(ix, iy1b, iw, iya - iy1b);
  1446.             if ( code < 0 )
  1447.               return code;
  1448.           }
  1449.         if ( iy1a > iya )
  1450.           code = (*fill_trap)(dev, pltop, prtop,
  1451.                       ya, y1a, false, pdevc, lop);
  1452.         else
  1453.           code = 0;
  1454.       }
  1455.     else
  1456.       {    /*
  1457.          * Clip the trapezoid if possible.  This can save a lot
  1458.          * of work when filling paths that cross band boundaries.
  1459.          */
  1460.         fixed yac;
  1461.             if ( pbox->p.y < ya )
  1462.           { code = (*fill_trap)(dev, plbot, prbot,
  1463.                     yb, ya, false, pdevc, lop);
  1464.             if ( code < 0 )
  1465.               return code;
  1466.             yac = ya;
  1467.           }
  1468.         else
  1469.           yac = pbox->p.y;
  1470.         if ( pbox->q.y > y1b )
  1471.           { code = (*fill_trap)(dev, &slant_left, &slant_right,
  1472.                     yac, y1b, false, pdevc, lop);
  1473.             if ( code < 0 )
  1474.               return code;
  1475.             code = (*fill_trap)(dev, pltop, prtop,
  1476.                     y1b, y1a, false, pdevc, lop);
  1477.           }
  1478.         else
  1479.           code = (*fill_trap)(dev, &slant_left, &slant_right,
  1480.                       yac, pbox->q.y, false, pdevc, lop);
  1481.       }
  1482.     return code;
  1483. }
  1484.  
  1485. /* Re-sort the x list by moving alp backward to its proper spot. */
  1486. private void near
  1487. resort_x_line(active_line *alp)
  1488. {    active_line *prev = alp->prev;
  1489.     active_line *next = alp->next;
  1490.     fixed nx = alp->x_current;
  1491.  
  1492.     prev->next = next;
  1493.     if ( next )
  1494.       next->prev = prev;
  1495.     while ( !x_precedes(prev, alp, nx) )
  1496.        {    if_debug2('f', "[f]swap 0x%lx,0x%lx\n",
  1497.                  (ulong)alp, (ulong)prev);
  1498.         next = prev, prev = prev->prev;
  1499.        }
  1500.     alp->next = next;
  1501.     alp->prev = prev;
  1502.     /* next might be null, if alp was in */
  1503.     /* the correct spot already. */
  1504.     if ( next )
  1505.       next->prev = alp;
  1506.     prev->next = alp;
  1507. }
  1508.